#include "gamemodel.h"

AiThread::AiThread(BoardState& state, int depth) : _state(state),
    _done(false), _depth(depth)
{

}

void AiThread::run()
{
    _move = _state.genBestMove(_depth);
    _done = true;
}

Move& AiThread::getMove()
{
    return _move;
}

bool AiThread::isDone()
{
    return _done;
}

GameModel::GameModel()
{
    _state.clear();
    _state.initPos();
    nMoves = _state.genLegalMoves(moveList);

    _thread = NULL;
    _aiDepth = 4;
}

GameModel::~GameModel()
{
    //dtor
}

int GameModel::getTurn()
{
    return _state.getTurn();
}

int GameModel::getPiece(int x, int y)
{
    return _state.getPiece(x, y);
}

int GameModel::getPieceColor(int piece)
{
    if(piece == W_KING || piece == W_QUEEN || piece == W_BISHOP ||
       piece == W_KNIGHT || piece == W_PAWN || piece == W_ROOK)
       return WHITE;
    else
        return BLACK;
}

bool GameModel::isMoveValid(int x0, int y0, int x1, int y1, int* moveId)
{
    for (int i = 0; i < nMoves; ++i) {
        if (moveList[i].getX1() == x0 && moveList[i].getY1() == y0 &&
                moveList[i].getX2() == x1 && moveList[i].getY2() == y1) {
            *moveId = i;
            return true;
        }
    }

    return false;
}

MoveResult GameModel::makeMove(const Move& move)
{
    _state.execMove(move);

    nMoves = _state.genLegalMoves(moveList);
    if (nMoves == 0) {
        if (_state.getTurn() == WHITE) {
            return BLACK_WIN;
        } else {
            return WHITE_WIN;
        }
    }

    return CONTINUE;
}

const Move& GameModel::getMove(int moveId)
{
    return moveList[moveId];
}

int GameModel::getNumMoves()
{
    return nMoves;
}

Move GameModel::getAiMove()
{
    if (_thread == NULL) {
        return Move();
    }

    Move m = _thread->getMove();

    if (_thread != NULL) {
        delete _thread;
        _thread = NULL;
    }

    return m;
}

bool GameModel::isPromotionMove(Move& move)
{
    if (move.getSpecialRule() == QUEEN || move.getSpecialRule() == ROOK ||
        move.getSpecialRule() == BISHOP || move.getSpecialRule() == KNIGHT) {

        return true;
    }
    return false;
}

const Move* GameModel::getPromotionMove(SpecialRuleType promType, int x, int y)
{
    for (int i = 0; i < nMoves; ++i) {
        if (moveList[i].getSpecialRule() == promType &&
                moveList[i].getX2() == x && moveList[i].getY2() == y) {
            return &moveList[i];
        }
    }
    return NULL;
}

void GameModel::startAiThread()
{
    _thread = new AiThread(_state, _aiDepth);
    _thread->setCancelModeAsynchronous();
    _thread->start();
}

bool GameModel::isAiThreadStarted()
{
    if (_thread != NULL) {
        return true;
    }
    return false;
}

void GameModel::setAiDepth(int depth)
{
    _aiDepth = depth;
}

bool GameModel::isReady()
{
    if (_thread != NULL) {
        return _thread->isDone();
    }
    return true;
}

void GameModel::reset()
{
    // Kill thread
    if (_thread != NULL) {
        _thread->cancel();
        //std::cout << "joining thread\n";
        _thread->join();
        //std::cout << "thread killed\n";
        delete _thread;
        _thread = NULL;
    }

    // Reset boardstate
    _state.clear();
    _state.initPos();
    nMoves = _state.genLegalMoves(moveList);

}
